home *** CD-ROM | disk | FTP | other *** search
/ PC User 2003 January / Disc 1 / PCU0103CD1.iso / entertn / demos / files / aomtrial.exe / AOM / AI / SCN15P3.XS < prev    next >
Encoding:
Text File  |  2002-09-05  |  21.9 KB  |  707 lines

  1. //==============================================================================
  2. // Scn15p3: AI Scenario Script for scenario 15 player 3
  3. //==============================================================================
  4. /*
  5.    AI owner:  Mike Kidd
  6.    Scenario owner: Jeff Brown
  7.  
  8.    Overview:
  9.    The player's task is to protect the relic sword, build up, and then find
  10.    a way to deliver it to the sleeping colossus in the fortified enemy town.
  11.  
  12.    The CP starts in the second age, maintaining a reserve of spearmen.  Starting
  13.    at nextAttackTime (adjusted for the time spent in cinematics, i.e. "startTime") 
  14.    and at attackInterval intervals after that, it sends an army of attackSize units.
  15.    AttackSize is multiplied by attackSizeMultiplier each time, to a max of maxAttackSize.
  16.  
  17.    In the third age, the CP maintains a reserve of chariot archers in addition to the 
  18.    spearmen, and adds anubites.  The attack groups will contain one anubite, a few
  19.    CAs, and a majority of spearmen.
  20.  
  21.    In the fourth age, the CP adds scorpionmen and avengers.  The attack groups will have 
  22.    a small number of myth units, several CAs, and the balance filled in with spearmen.
  23.  
  24.    Unit line and armory upgrades are added through the ages.
  25.  
  26.    The CP will invoke Vision somewhere in the general area of the player's TC.  
  27.    (Vector +/- 50m in X and Z.)  The CP can use Serpents and Ancestors as needed, 
  28.    generally near an army or near the city gates.  Tornado is reserved for trigger effects.
  29.  
  30.    This script receives outerWall() and innerWall() alerts when the walls are 
  31.    endangered, and it reacts by drafting an ad-hoc army for defense.
  32.  
  33.    Difficulty: Implemented 7/15
  34.  
  35.    8/20/2002:  Reduced gather range on defend plan to relieve congestion at barracks.
  36.  
  37.    9/05/2002:  Reduced strength of defend plans on all levels, other minor difficulty adjustments
  38.      
  39. */
  40. //==============================================================================
  41.  
  42.  
  43. include "scn lib.xs";
  44.  
  45.  
  46. // *****************************************************************************
  47. //
  48. // Globals
  49. //
  50. // *****************************************************************************
  51.  
  52. // Attack routes
  53. int   routeEast = -1;
  54. int   routeWest = -1;
  55.  
  56.  
  57. // Army control
  58. int   lastAttackPlan = -1;     // Used to find "my army" for god power position info
  59. int   defendPlan = -1;
  60. int   nextAttackTime = 300000;   // Will be adjusted for the wakeup time
  61. int   attackInterval = 240000;   // Attack every 4 minutes
  62. float   attackSize = 3.0;
  63. float attackMultiplier = 1.2;
  64. int   maxAttackSize = 10;
  65.  
  66. int   spearmanMaintain = -1;     // Plan to maintain spearman pop
  67. int   chariotArcherMaintain = -1;
  68. int   anubiteMaintain = -1;
  69. int   scorpionManMaintain = -1;
  70. int   avengerMaintain = -1;
  71.  
  72. int   spearmanQty = 4;         // Quantity to maintain
  73. int   spearmanDelay = 30;       // Interval between training units
  74. int   chariotQty = 4;         // Quantity to maintain
  75. int   chariotDelay = 30;       // Interval between training units
  76. int   anubiteQty = 1;         // Quantity to maintain
  77. int   anubiteDelay = 90;       // Interval between training units
  78. int   scorpionQty = 1;         // Quantity to maintain
  79. int   scorpionDelay = 90;       // Interval between training units
  80. int   avengerQty = 1;         // Quantity to maintain
  81. int   avengerDelay = 90;       // Interval between training units
  82.  
  83.  
  84.  
  85. // Cinematic blocks
  86. const string   cbInnerGate = "1450"; 
  87. const string   cbOuterGate = "1451"; 
  88. const string   cbEastRoute1 = "1452"; 
  89. const string   cbEastRoute2 = "1453"; 
  90. const string   cbEastRoute3 = "1454"; 
  91. const string   cbEastRoute4 = "1459"; 
  92. const string   cbWestRoute1 = "1455"; 
  93. const string   cbWestRoute2 = "1456"; 
  94. const string   cbWestRoute3 = "1458"; 
  95. //const string   cbSettlementNorth = "1457"; 
  96. const string   cbSettlementCenter = "1460"; 
  97. //const string   cbSettlementSouth = "1461"; 
  98. const string   cbGuardian = "1462"; 
  99. const string   cbBarracksGather = "1463"; 
  100. const string   cbTempleGather = "1464"; 
  101. const string   cbMigdolGather = "1465"; 
  102. const string   cbCourtyard = "3263";   // Front courtyard inside outer gates
  103. const string   cbDefendPoint = "3259"; // Center of defend zone
  104.  
  105.  
  106. // Misc.
  107. int   age3Time = 1200000;   // 20 min
  108. int   age4Time = 36000000;  // 10 hours!
  109. int   startTime = -1;      // Time of the wakeup() function
  110. int   useVisionTime = -1;  // Time to use vision god power
  111.  
  112.  
  113. // *****************************************************************************
  114. //
  115. //                                FUNCTIONS
  116. //
  117. // *****************************************************************************
  118.  
  119.  
  120. // Called by trigger when the cinematics are done
  121. void wakeup(int parm=-1)
  122. {
  123.    static bool alreadyRun = false;
  124.    aiEcho("Wakeup running at "+timeString());
  125.    if (alreadyRun == true)
  126.       return;
  127.    alreadyRun = true;
  128.  
  129.    startTime = xsGetTime();
  130.    age3Time = age3Time + startTime;    // Adjust for delay in wakeup. 
  131.    xsEnableRule("goToAge3");
  132.    age4Time = age4Time + startTime;
  133.    nextAttackTime = nextAttackTime + startTime;
  134.    useVisionTime = startTime+30000+aiRandInt(120)*1000;   // Use vision 30-150 seconds from now
  135.  
  136.    xsEnableRule("useVision");
  137.    xsEnableRule("scout");
  138.    xsEnableRule("getAge2UnitUpgrades");
  139.    xsEnableRule("getAge2ArmoryUpgrades");
  140.    xsEnableRule("attackGenerator");
  141.    spearmanMaintain = maintainUnit(cUnitTypeSpearman, spearmanQty, kbGetBlockPosition(cbBarracksGather), spearmanDelay);
  142.    chariotArcherMaintain = maintainUnit(cUnitTypeChariotArcher, chariotQty, kbGetBlockPosition(cbMigdolGather), chariotDelay);
  143.    anubiteMaintain = maintainUnit(cUnitTypeAnubite, anubiteQty, kbGetBlockPosition(cbTempleGather), anubiteDelay) ;
  144.    // Maintain myth units
  145.    scorpionManMaintain = maintainUnit(cUnitTypeScorpionMan, scorpionQty, kbGetBlockPosition(cbTempleGather), scorpionDelay);
  146.    avengerMaintain = maintainUnit(cUnitTypeAvenger, avengerQty, kbGetBlockPosition(cbTempleGather), avengerDelay);
  147.  
  148.  
  149.    // Init low-priority defend plan 
  150.    defendPlan =aiPlanCreate("Defend Plan", cPlanDefend);
  151.    if (defendPlan >= 0)
  152.    {
  153.       aiPlanAddUnitType(defendPlan, cUnitTypeMilitary, 0, 200, 200);    // All unassigned mil units
  154.       aiPlanSetDesiredPriority(defendPlan, 10);                       // Way low, below scouting and attack
  155.       aiPlanSetVariableVector(defendPlan, cDefendPlanDefendPoint, 0, kbGetBlockPosition(cbDefendPoint));
  156.       aiPlanSetVariableFloat(defendPlan, cDefendPlanEngageRange, 0, 100);
  157.       aiPlanSetVariableBool(defendPlan, cDefendPlanPatrol, 0, false);
  158.       aiPlanSetVariableFloat(defendPlan, cDefendPlanGatherDistance, 0, 20.0);
  159.       aiPlanSetInitialPosition(defendPlan, kbGetBlockPosition(cbDefendPoint));
  160.       aiPlanSetUnitStance(defendPlan, cUnitStanceDefensive);
  161.  
  162.       aiPlanSetVariableInt(defendPlan, cDefendPlanRefreshFrequency, 0, 5);
  163.       aiPlanSetNumberVariableValues(defendPlan, cDefendPlanAttackTypeID, 2, true);
  164.       aiPlanSetVariableInt(defendPlan, cDefendPlanAttackTypeID, 0, cUnitTypeUnit);
  165.       aiPlanSetVariableInt(defendPlan, cDefendPlanAttackTypeID, 1, cUnitTypeBuilding);
  166.  
  167.       aiEcho("Creating defend plan");
  168.       aiPlanSetActive(defendPlan); 
  169.    }
  170. }
  171.  
  172. /*
  173. //  Called via trigger when the outer wall is in danger of falling...AI should rally nearby units
  174. void outerWall(int parm=-1)
  175. {
  176.    int   count=0;
  177.    int   attackID=aiPlanCreate("Outer Wall Attack", cPlanAttack);
  178.  
  179.    // Rally units to defend...all units within 40 meters, to a maximum of 10 units
  180.    aiEcho("Outer wall emergency.");
  181.    count = getUnassignedUnitCount(kbGetBlockPosition(cbOuterGate), 40.0, 2, cUnitTypeMilitary);
  182.    if (count > 10)
  183.       count = 10;
  184.    
  185.    if (attackID < 0)
  186.       return;
  187.  
  188.    if (aiPlanSetVariableInt(attackID, cAttackPlanPlayerID, 0, 1) == false)
  189.       return;
  190.  
  191.    aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit);
  192.  
  193.    aiPlanSetVariableVector(attackID, cAttackPlanGatherPoint, 0, kbGetBlockPosition(cbTempleGather));
  194.    aiPlanSetVariableFloat(attackID, cAttackPlanGatherDistance, 0, 25.0);
  195.    aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbTempleGather));
  196.  
  197.    aiPlanAddUnitType(attackID, cUnitTypeMilitary, 1, count, count );
  198.  
  199.    aiEcho("Responding with "+count+" units.");
  200.    aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbOuterGate));
  201.    aiPlanSetRequiresAllNeedUnits(attackID, true);
  202.    aiPlanSetActive(attackID);
  203. }
  204.  
  205. //  Called via trigger when the inner wall is in danger of falling...AI should throw everything at it
  206. void innerWall(int parm=-1)
  207. {
  208.      // Rally units to defend...anywhere on the map, up to 30 units
  209.  
  210.    int   count=0;
  211.    int   attackID=aiPlanCreate("Inner Wall Attack", cPlanAttack);
  212.  
  213.    aiEcho("Inner wall emergency.");
  214.    count = getUnassignedUnitCount(kbGetBlockPosition(cbInnerGate), 200.0, 2, cUnitTypeMilitary);
  215.    if (count > 30)
  216.       count = 30;
  217.    
  218.    if (attackID < 0)
  219.       return;
  220.  
  221.    if (aiPlanSetVariableInt(attackID, cAttackPlanPlayerID, 0, 1) == false)
  222.       return;
  223.  
  224.    aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit);
  225.    aiPlanSetVariableVector(attackID, cAttackPlanGatherPoint, 0, kbGetBlockPosition(cbTempleGather));
  226.    aiPlanSetVariableFloat(attackID, cAttackPlanGatherDistance, 0, 25.0);
  227.    aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbTempleGather));
  228.  
  229.  
  230.  
  231.    aiPlanAddUnitType(attackID, cUnitTypeMilitary, 1, count, count );
  232.  
  233.    aiEcho("Responding with "+count+" units.");
  234.    aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbInnerGate));
  235.    aiPlanSetRequiresAllNeedUnits(attackID, true);
  236.    aiPlanSetActive(attackID);
  237. }
  238. */
  239.  
  240.  
  241. void age2EventHandler(int bogus=-1)
  242. {
  243.    //xsEnableRule("useSerpents");
  244.  
  245. }
  246.  
  247.  
  248.  
  249. void age3EventHandler(int bogus=-1)
  250. {
  251.    xsEnableRule("useAncestors");
  252.    xsEnableRule("goToAge4");
  253.    xsEnableRule("getAge3UnitUpgrades");
  254.    xsEnableRule("getAge3ArmoryUpgrades");
  255.  
  256. }
  257.  
  258.  
  259.  
  260. void age4EventHandler(int bogus=-1)
  261. {
  262.    //DO NOT USE TORNADO.  Rerserved for trigger use!
  263.    xsEnableRule("getAge4UnitUpgrades");
  264.    xsEnableRule("getAge4ArmoryUpgrades");
  265. }
  266.  
  267.  
  268.  
  269.  
  270. void attack(int size=0)
  271. {
  272.  
  273.    int min=0;
  274.    int sec=0;
  275.  
  276.    int   attackID=aiPlanCreate("Attack at "+timeString(), cPlanAttack);
  277.    if (attackID < 0)
  278.       return;
  279.  
  280.    if (aiPlanSetVariableInt(attackID, cAttackPlanPlayerID, 0, 1) == false)
  281.       return;
  282.  
  283.    if (aiPlanSetNumberVariableValues(attackID, cAttackPlanTargetTypeID, 2, true) == false)
  284.       return;
  285.  
  286.    aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit);
  287.    aiPlanSetVariableInt(attackID, cAttackPlanTargetTypeID, 1, cUnitTypeBuilding);
  288.  
  289.    if (aiRandInt(2) == 0)
  290.       aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeWest);
  291.    else 
  292.       aiPlanSetVariableInt(attackID, cAttackPlanAttackRouteID, 0, routeEast);
  293.  
  294.  
  295.    aiPlanSetVariableVector(attackID, cAttackPlanGatherPoint, 0, kbGetBlockPosition(cbTempleGather));
  296.    aiPlanSetVariableFloat(attackID, cAttackPlanGatherDistance, 0, 25.0);
  297.  
  298.    switch(kbGetAge())
  299.    {
  300.    case cAge2:
  301.       {  // All spearmen
  302.          aiPlanAddUnitType(attackID, cUnitTypeSpearman, 0, size, size );
  303.          break;
  304.       }
  305.    case cAge3:
  306.       {  // 70% spear, 30% CA, plus one myth unit
  307.          aiPlanAddUnitType(attackID, cUnitTypeSpearman, 0, ((7*size+5))/10, ((7*size+5))/10 );
  308.          aiPlanAddUnitType(attackID, cUnitTypeChariotArcher, 0, ((3*size+5))/10, ((3*size+5))/10 );
  309.          aiPlanAddUnitType(attackID, cUnitTypeMythUnit, 0, 1, 1);
  310.  
  311.          break;
  312.       }
  313.    case cAge4:
  314.       {  // 50% spear, 30% CA, 20% myth
  315.          aiPlanAddUnitType(attackID, cUnitTypeSpearman, 0, size/2, size/2 );
  316.          aiPlanAddUnitType(attackID, cUnitTypeChariotArcher, 0, (3*size)/10, (3*size)/10 );
  317.          aiPlanAddUnitType(attackID, cUnitTypeMythUnit, 0, (size+2)/5, (size+2)/5 );
  318.          break;
  319.       }
  320.    }
  321.  
  322.    aiPlanSetInitialPosition(attackID, kbGetBlockPosition(cbTempleGather));
  323.    aiPlanSetRequiresAllNeedUnits(attackID, true);
  324.    aiPlanSetActive(attackID);
  325.    aiEcho("Activating attack plan "+attackID+" with appx "+size+" units.");
  326.    lastAttackPlan = attackID; // update the global var
  327. }
  328.  
  329.  
  330.  
  331.  
  332.  
  333. void main()
  334. {
  335.    aiEcho("Starting Scn15p3.xs");
  336.  
  337.  
  338.    //Calculate some areas.
  339.    kbAreaCalculate(1200.0);
  340.    aiRandSetSeed();
  341.    kbSetTownLocation(kbGetBlockPosition(cbTempleGather));
  342.  
  343.    aiSetAttackResponseDistance(20.0);
  344.  
  345.    // Kill escrows
  346.    kbEscrowSetPercentage( cEconomyEscrowID, cAllResources, 0.0);
  347.    kbEscrowSetPercentage( cMilitaryEscrowID, cAllResources, 0.0);
  348.    kbEscrowAllocateCurrentResources();
  349.  
  350.  
  351.    aiSetAgeEventHandler(cAge2, "age2EventHandler");
  352.    aiSetAgeEventHandler(cAge3, "age3EventHandler");
  353.    aiSetAgeEventHandler(cAge4, "age4EventHandler");
  354.  
  355.    routeWest = attackRoute("West Attack Route",cbInnerGate, cbWestRoute1,cbWestRoute2);
  356.    routeEast = attackRoute("East Attack Route",cbInnerGate, cbEastRoute1, cbEastRoute2, cbEastRoute3);
  357.    
  358.    aiEcho("Difficulty = "+aiGetWorldDifficulty());
  359.    switch (aiGetWorldDifficulty())
  360.    {  // Note:  Difficulty 0 takes the defaults
  361.    case 1:
  362.       {
  363.          spearmanQty = 10;
  364.          spearmanDelay = 30;
  365.          chariotQty = 6;
  366.          chariotDelay = 30;
  367.          anubiteQty = 2;
  368.          anubiteDelay = 90;
  369.          scorpionQty = 2;
  370.          scorpionDelay = 90;
  371.          avengerQty = 2;
  372.          avengerDelay = 90;
  373.          nextAttackTime = 300000;
  374.          attackInterval = 240000;
  375.          attackSize = 3.0;
  376.          attackMultiplier = 1.2;
  377.          maxAttackSize = 12;
  378.          age3Time = 20*60*1000;   
  379.          age4Time = 40*60*1000; 
  380.          break;
  381.    }
  382.    case 2:
  383.       {
  384.          spearmanQty = 20;
  385.          spearmanDelay = 30;
  386.          chariotQty = 12;
  387.          chariotDelay = 30;
  388.          anubiteQty = 3;
  389.          scorpionQty = 3;
  390.          avengerQty = 3;
  391.          scorpionDelay = 60;
  392.          avengerDelay = 60;
  393.          anubiteDelay = 60;
  394.          nextAttackTime = 180000;
  395.          attackInterval = 180000;
  396.          attackSize = 5.0;
  397.          attackMultiplier = 1.2;
  398.          maxAttackSize = 25;
  399.          age3Time = 15*60*1000;   
  400.          age4Time = 25*60*1000;  
  401.          break;
  402.    }
  403.    case 3:
  404.       {
  405.          spearmanQty = 30;
  406.          spearmanDelay = 20;
  407.          chariotQty = 20;
  408.          chariotDelay = 20;
  409.          anubiteQty = 5;
  410.          scorpionQty = 5;
  411.          avengerQty = 5;
  412.          scorpionDelay = 40;
  413.          avengerDelay = 40;
  414.          anubiteDelay = 40;
  415.          nextAttackTime = 30000;
  416.          attackInterval = 180000;
  417.          attackSize = 6.0;
  418.          attackMultiplier = 1.3;
  419.          maxAttackSize = 35;
  420.          age3Time = 10*60*1000;   
  421.          age4Time = 20*60*1000;  
  422.          break;
  423.       }
  424.    }
  425. }
  426.  
  427.  
  428.  
  429.  
  430.  
  431.  
  432.  
  433. // *****************************************************************************
  434. //
  435. // RULES
  436. //
  437. // *****************************************************************************
  438.  
  439. rule scout
  440.    inactive
  441.    minInterval 5
  442. {
  443.    // just set up an explore plan
  444.    int exploreID = aiPlanCreate("Explore", cPlanExplore);
  445.    if(exploreID >= 0)
  446.    {
  447.       aiPlanSetVariableFloat( exploreID, cExplorePlanLOSMultiplier,  0, 4.0 );
  448.       aiPlanAddUnitType(exploreID, cUnitTypeSpearman, 1, 1, 1);
  449.       aiPlanSetActive(exploreID);
  450.    }
  451.    xsDisableSelf();
  452. }
  453.  
  454.  
  455. rule goToAge3
  456.    inactive
  457.    mininterval 20
  458. {
  459.    if ( xsGetTime() < age3Time )
  460.       return;
  461.    researchTech(cTechAge3Nephthys);
  462.    xsDisableSelf();
  463. }
  464.  
  465.  
  466. rule goToAge4
  467.    inactive
  468.    mininterval 20
  469. {
  470.    if ( xsGetTime() < age4Time )
  471.       return;
  472.    researchTech(cTechAge4Horus);
  473.    xsDisableSelf();
  474. }
  475.  
  476.  
  477.  
  478. rule getAge2UnitUpgrades
  479.    inactive
  480.    minInterval 20
  481. {
  482.    if ( xsGetTime() < (startTime + startTime + age3Time)/3 )
  483.       return;     // Wait till 1/3 to age3
  484.    researchTech(cTechMediumAxemen);
  485.    researchTech(cTechMediumSlingers);
  486.    researchTech(cTechMediumSpearmen);
  487.    xsDisableSelf();
  488. }
  489.  
  490. rule getAge2ArmoryUpgrades
  491.    inactive
  492.    minInterval 20
  493. {
  494.    if ( xsGetTime() < (startTime + age3Time + age3Time)/3 )
  495.       return;     // Wait till 2/3 to age3
  496.    aiEcho("Getting age 2 armory upgrades");
  497.    researchTech(cTechCopperWeapons);
  498.    researchTech(cTechCopperMail);
  499.    researchTech(cTechCopperShields);
  500.    xsDisableSelf();
  501. }
  502.  
  503. rule getAge3UnitUpgrades
  504.    inactive
  505.    minInterval 20
  506. {
  507.    if ( xsGetTime() < (age3Time+180000) )
  508.       return;
  509.    researchTech(cTechHeavyAxemen);
  510.    researchTech(cTechHeavySlingers);
  511.    researchTech(cTechHeavySpearmen);
  512.    researchTech(cTechHeavyChariots);
  513.    xsDisableSelf();
  514. }
  515.  
  516. rule getAge3ArmoryUpgrades
  517.    inactive
  518.    minInterval 20
  519. {
  520.    if ( xsGetTime() < (age3Time+300000) )
  521.       return;
  522.    researchTech(cTechBronzeWeapons);
  523.    researchTech(cTechBronzeMail);
  524.    researchTech(cTechBronzeShields);
  525.    xsDisableSelf();
  526. }
  527.  
  528. rule getAge4UnitUpgrades
  529.    inactive
  530.    minInterval 20
  531. {
  532.    if ( xsGetTime() < (age4Time+180000) )
  533.       return;
  534.    researchTech(cTechChampionAxemen);
  535.    researchTech(cTechChampionSlingers);
  536.    researchTech(cTechChampionSpearmen);
  537.    researchTech(cTechChampionChariots);
  538.    xsDisableSelf();
  539. }
  540.  
  541. rule getAge4ArmoryUpgrades
  542.    inactive
  543.    minInterval 20
  544. {
  545.    if ( xsGetTime() < (age4Time+300000) )
  546.       return;
  547.    researchTech(cTechIronWeapons);
  548.    researchTech(cTechIronMail);
  549.    researchTech(cTechIronShields);
  550.    xsDisableSelf();
  551. }
  552.  
  553.  
  554.  
  555. rule attackGenerator
  556.    minInterval 10
  557.    inactive
  558. {
  559.    //aiEcho("attack check running, next time is "+nextAttackTime);
  560.    if ( xsGetTime() < nextAttackTime )
  561.       return;
  562.  
  563.    attack(attackSize);
  564.    nextAttackTime = xsGetTime() + attackInterval;
  565.    attackSize = attackSize * attackMultiplier;
  566.    if (attackSize > maxAttackSize)
  567.       attackSize = maxAttackSize;
  568.    aiEcho("Next attack size will be "+attackSize+".");
  569. }
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576. rule useVision       // When it's time, cast vision at P1 TC +/- 50 meters
  577.    minInterval 5
  578.    inactive
  579. {
  580.    if ( xsGetTime() < useVisionTime )
  581.       return;
  582.  
  583.    vector aimHere = vector(-1,-1,-1);
  584.    int dx = -50;
  585.    int dz = -50;
  586.    dx = dx+aiRandInt(100);
  587.    dz = dz+aiRandInt(100);     // aim at middle TC +/- 50 meters in X and Z
  588.    aimHere = kbGetBlockPosition(cbSettlementCenter);
  589.    aimHere = xsVectorSetX(aimHere, xsVectorGetX(aimHere)+dx);
  590.    aimHere = xsVectorSetZ(aimHere, xsVectorGetZ(aimHere)+dz);
  591.  
  592.    if (aiCastGodPowerAtPosition(cTechVision, aimHere) == true)
  593.    {
  594.       aiEcho("Vision has been used at "+aimHere);
  595.       xsDisableSelf();
  596.    }
  597. }
  598.  
  599.  
  600. rule useSerpents 
  601.    minInterval 5
  602.    inactive
  603. {
  604.    // look for a group of 5 enemy units, at the inner gate or at my main army's location
  605.    int targetUnit = -1;
  606.  
  607.    
  608.    static int tempQuery = -1;
  609.    if (tempQuery < 0)
  610.    {  // Doesn't exist, set it up
  611.       tempQuery = kbUnitQueryCreate("useSerpents1");
  612.       if ( configQuery(tempQuery, cUnitTypeUnit, -1, cUnitStateAlive, 1, kbGetBlockPosition(cbInnerGate), true, 75) == false)
  613.          return;
  614.    }
  615.    kbUnitQueryResetResults(tempQuery);
  616.    int targetCount = kbUnitQueryExecute(tempQuery); 
  617.  
  618.    if (targetCount < 5)
  619.    {
  620.       if (lastAttackPlan < 0)
  621.          return;
  622.       vector pVec = aiPlanGetLocation(lastAttackPlan);
  623.       if (xsVectorGetX(pVec)>=0)
  624.       {
  625.          static int tempQuery2 = -1;
  626.          if (tempQuery2 < 0)
  627.          {  // Doesn't exist, set it up
  628.             tempQuery2 = kbUnitQueryCreate("useSerpents2");
  629.             if ( configQuery(tempQuery2, cUnitTypeMilitary, -1, cUnitStateAlive, 1, pVec, true, 50) == false)
  630.                return;
  631.          }
  632.          else
  633.             kbUnitQuerySetPosition(tempQuery, pVec); // Because pVec changes as army moves
  634.          kbUnitQueryResetResults(tempQuery2);
  635.          targetCount = kbUnitQueryExecute(tempQuery2); 
  636.          if (targetCount < 5)
  637.             return;
  638.          else
  639.             targetUnit = kbUnitQueryGetResult(tempQuery2, 0);  // grab first unit
  640.       }
  641.    } 
  642.    else
  643.       targetUnit = kbUnitQueryGetResult(tempQuery, targetCount/2);  // grab middle unit
  644.  
  645.  
  646.    aiEcho("Using Plague of Serpents at "+kbUnitGetPosition(targetUnit));
  647.    if ( aiCastGodPowerAtPosition(cTechSerpents, kbUnitGetPosition(targetUnit)) == true)
  648.       xsDisableSelf();
  649.    else
  650.       aiEcho("Serpents failed at "+kbUnitGetPosition(targetUnit));
  651. }
  652.  
  653.  
  654. rule useAncestors // Same logic as Serpents, look for enemy military units
  655.    minInterval 5
  656.    inactive
  657. {
  658.    // look for a group of 5 enemy units, at the Migdol location or at my main army's location
  659.    int targetUnit = -1;
  660.  
  661.    static int tempQuery = -1;
  662.    if (tempQuery < 0)
  663.    {  // Doesn't exist, set it up
  664.       tempQuery = kbUnitQueryCreate("useAncestors1");
  665.       if ( configQuery(tempQuery, cUnitTypeUnit, -1, cUnitStateAlive, 1, kbGetBlockPosition(cbInnerGate), true, 75) == false)
  666.          return;
  667.    }
  668.    kbUnitQueryResetResults(tempQuery);
  669.    int targetCount = kbUnitQueryExecute(tempQuery); 
  670.  
  671.    if (targetCount < 5)
  672.    {
  673.       vector pVec = aiPlanGetLocation(lastAttackPlan);
  674.       if (xsVectorGetX(pVec)>=0)
  675.       {
  676.          static int tempQuery2 = -1;
  677.          if (tempQuery2 < 0)
  678.          {  // Doesn't exist, set it up
  679.             tempQuery2 = kbUnitQueryCreate("useAncestors2");
  680.             if ( configQuery(tempQuery2, cUnitTypeMilitary, -1, cUnitStateAlive, 1, pVec, true, 50) == false)
  681.                return;
  682.          }
  683.          else
  684.             kbUnitQuerySetPosition(tempQuery, pVec); // Because pVec changes as army moves
  685.          kbUnitQueryResetResults(tempQuery2);
  686.          targetCount = kbUnitQueryExecute(tempQuery2); 
  687.          if (targetCount < 5)
  688.             return;
  689.          else
  690.             targetUnit = kbUnitQueryGetResult(tempQuery2, 0);  // grab first unit
  691.       }
  692.       else
  693.          return;  // No army to check
  694.    } 
  695.    else//SkeletonPower//PharaohRespawnCityoftheDead
  696.       targetUnit = kbUnitQueryGetResult(tempQuery, targetCount/2);  // grab middle unit
  697.  
  698.  
  699.    aiEcho("Using Ancestors");
  700.    if ( aiCastGodPowerAtPosition(cTechSkeletonPower, kbUnitGetPosition(targetUnit)) == true)
  701.       xsDisableSelf();
  702.    else
  703.       aiEcho("Ancestors failed at "+kbUnitGetPosition(targetUnit));
  704. }
  705.  
  706.  
  707.